home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / bin / debconf-apt-progress < prev    next >
Text File  |  2009-10-02  |  12KB  |  486 lines

  1. #!/usr/bin/perl -w
  2. # This file was preprocessed, do not edit!
  3.  
  4.  
  5. use strict;
  6. use POSIX;
  7. use Fcntl;
  8. use Getopt::Long;
  9. use Debconf::Client::ConfModule ();
  10.  
  11. my ($config, $start, $from, $to, $stop);
  12. my $progress=1;
  13. my $dlwaypoint=15;
  14. my ($logfile, $logstderr);
  15. my $had_frontend;
  16.  
  17. sub checkopen (@) {
  18.     my $file = $_[0];
  19.     my $fd = POSIX::open($file, &POSIX::O_RDONLY);
  20.     defined $fd or die "$0: can't open $_[0]: $!\n";
  21.     return $fd;
  22. }
  23.  
  24. sub checkclose ($) {
  25.     my $fd = $_[0];
  26.     unless (POSIX::close($fd)) {
  27.         return if $! == &POSIX::EBADF;
  28.         die "$0: can't close fd $fd: $!\n";
  29.     }
  30. }
  31.  
  32. sub checkdup2 ($$) {
  33.     my ($oldfd, $newfd) = @_;
  34.     checkclose($newfd);
  35.     POSIX::dup2($oldfd, $newfd)
  36.         or die "$0: can't dup fd $oldfd to $newfd: $!\n";
  37. }
  38.  
  39. sub nocloexec (*) {
  40.     my $fh = shift;
  41.     my $flags = fcntl($fh, F_GETFD, 0);
  42.     fcntl($fh, F_SETFD, $flags & ~FD_CLOEXEC);
  43. }
  44.  
  45. sub nonblock (*) {
  46.     my $fh = shift;
  47.     my $flags = fcntl($fh, F_GETFL, 0);
  48.     fcntl($fh, F_SETFL, $flags | O_NONBLOCK);
  49. }
  50.  
  51. sub reservefds (@) {
  52.     my $null = checkopen('/dev/null');
  53.     my $close = 1;
  54.     for my $fd (@_) {
  55.         if ($null == $fd) {
  56.             $close = 0;
  57.         } else {
  58.             checkclose($fd);
  59.             checkdup2($null, $fd);
  60.         }
  61.     }
  62.     if ($close) {
  63.         checkclose($null);
  64.     }
  65. }
  66.  
  67. sub envnonempty ($) {
  68.     my $name = shift;
  69.     return (exists $ENV{$name} and $ENV{$name} ne '');
  70. }
  71.  
  72. sub start_debconf (@) {
  73.     if (! $ENV{DEBIAN_HAS_FRONTEND}) {
  74.         if (envnonempty('DEBCONF_DB_REPLACE')) {
  75.             $ENV{DEBCONF_APT_PROGRESS_DB_REPLACE} =
  76.                 $ENV{DEBCONF_DB_REPLACE};
  77.         }
  78.         if (envnonempty('DEBCONF_DB_OVERRIDE')) {
  79.             $ENV{DEBCONF_APT_PROGRESS_DB_OVERRIDE} =
  80.                 $ENV{DEBCONF_DB_OVERRIDE};
  81.         }
  82.  
  83.         $ENV{DEBCONF_DB_REPLACE} = 'configdb';
  84.         $ENV{DEBCONF_DB_OVERRIDE} = 'Pipe{infd:none outfd:none}';
  85.  
  86.         $ENV{DEBCONF_APT_PROGRESS_NO_FRONTEND} = 1;
  87.  
  88.         @ARGV = @_;
  89.     }
  90.  
  91.     import Debconf::Client::ConfModule;
  92. }
  93.  
  94. sub passthrough (@) {
  95.     my $priority = Debconf::Client::ConfModule::get('debconf/priority');
  96.  
  97.     defined(my $pid = fork) or die "$0: can't fork: $!\n";
  98.     if (!$pid) {
  99.         close STATUS_READ;
  100.         close COMMAND_WRITE;
  101.         close DEBCONF_COMMAND_READ;
  102.         close DEBCONF_REPLY_WRITE;
  103.         $^F = 6; # avoid close-on-exec
  104.         if (fileno(COMMAND_READ) != 0) {
  105.             checkdup2(fileno(COMMAND_READ), 0);
  106.             close COMMAND_READ;
  107.         }
  108.         if (fileno(APT_LOG) != 1) {
  109.             checkclose(1);
  110.             checkdup2(fileno(APT_LOG), 1);
  111.         }
  112.         if (fileno(APT_LOG) != 2) {
  113.             checkclose(2);
  114.             checkdup2(fileno(APT_LOG), 2);
  115.         }
  116.         close APT_LOG;
  117.         delete $ENV{DEBIAN_HAS_FRONTEND};
  118.         delete $ENV{DEBCONF_REDIR};
  119.         delete $ENV{DEBCONF_SYSTEMRC};
  120.         delete $ENV{DEBCONF_PIPE}; # just in case ...
  121.         $ENV{DEBIAN_FRONTEND} = 'passthrough';
  122.         $ENV{DEBIAN_PRIORITY} = $priority;
  123.         $ENV{DEBCONF_READFD} = 5;
  124.         $ENV{DEBCONF_WRITEFD} = 6;
  125.         $ENV{APT_LISTCHANGES_FRONTEND} = 'none';
  126.         if ($had_frontend) {
  127.             $ENV{DEBCONF_DB_REPLACE} = 'configdb';
  128.             $ENV{DEBCONF_DB_OVERRIDE} = 'Pipe{infd:none outfd:none}';
  129.         }
  130.         exec @_;
  131.     }
  132.  
  133.     close STATUS_WRITE;
  134.     close COMMAND_READ;
  135.     close DEBCONF_COMMAND_WRITE;
  136.     close DEBCONF_REPLY_READ;
  137.     return $pid;
  138. }
  139.  
  140. sub handle_status ($$$) {
  141.     my ($from, $to, $line) = @_;
  142.     my ($status, $pkg, $percent, $description) = split ':', $line, 4;
  143.  
  144.     my ($min, $len);
  145.     if ($status eq 'dlstatus') {
  146.         $min = 0;
  147.         $len = $dlwaypoint;
  148.     }
  149.     elsif ($status eq 'pmstatus') {
  150.         $min = $dlwaypoint;
  151.         $len = 100 - $dlwaypoint;
  152.     }
  153.     elsif ($status eq 'media-change') {
  154.         Debconf::Client::ConfModule::subst(
  155.             'debconf-apt-progress/media-change', 'MESSAGE',
  156.             $description);
  157.         my @ret = Debconf::Client::ConfModule::input(
  158.             'critical', 'debconf-apt-progress/media-change');
  159.         $ret[0] == 0 or die "Can't display media change request!\n";
  160.         Debconf::Client::ConfModule::go();
  161.         print COMMAND_WRITE "\n" || die "can't talk to command fd: $!";
  162.         return;
  163.     }
  164.     else {
  165.         return;
  166.     }
  167.  
  168.     $percent = ($percent * $len / 100 + $min);
  169.     $percent = ($percent * ($to - $from) / 100 + $from);
  170.     $percent =~ s/\..*//;
  171.     if ($progress) {
  172.         my @ret=Debconf::Client::ConfModule::progress('SET', $percent);
  173.         if ($ret[0] eq '30') {
  174.             cancel();
  175.         }
  176.     }
  177.     Debconf::Client::ConfModule::subst(
  178.         'debconf-apt-progress/info', 'DESCRIPTION', $description);
  179.     my @ret=Debconf::Client::ConfModule::progress(
  180.         'INFO', 'debconf-apt-progress/info');
  181.     if ($ret[0] eq '30') {
  182.         cancel();
  183.     }
  184. }
  185.  
  186. sub handle_debconf_command ($) {
  187.     my $line = shift;
  188.  
  189.     print "$line\n" || die "can't write to stdout: $!";
  190.     my $ret = <STDIN>;
  191.     chomp $ret;
  192.     print DEBCONF_REPLY_WRITE "$ret\n" ||
  193.         die "can't write to DEBCONF_REPLY_WRITE: $!";
  194. }
  195.  
  196. my $pid;
  197. sub run_progress ($$@) {
  198.     my $from = shift;
  199.     my $to = shift;
  200.     my $command = shift;
  201.     local (*STATUS_READ, *STATUS_WRITE);
  202.     local (*COMMAND_READ, *COMMAND_WRITE);
  203.     local (*DEBCONF_COMMAND_READ, *DEBCONF_COMMAND_WRITE);
  204.     local (*DEBCONF_REPLY_READ, *DEBCONF_REPLY_WRITE);
  205.     local *APT_LOG;
  206.     use IO::Handle;
  207.  
  208.     if ($progress) {
  209.         my @ret=Debconf::Client::ConfModule::progress(
  210.             'INFO', 'debconf-apt-progress/preparing');
  211.         if ($ret[0] eq '30') {
  212.             cancel();
  213.             return 30;
  214.         }
  215.     }
  216.  
  217.     reservefds(4, 5, 6);
  218.  
  219.     pipe STATUS_READ, STATUS_WRITE
  220.         or die "$0: can't create status pipe: $!";
  221.     nonblock(\*STATUS_READ);
  222.     checkdup2(fileno(STATUS_WRITE), 4);
  223.     open STATUS_WRITE, '>&=4'
  224.         or die "$0: can't reopen STATUS_WRITE as fd 4: $!";
  225.     nocloexec(\*STATUS_WRITE);
  226.  
  227.     pipe COMMAND_READ, COMMAND_WRITE
  228.         or die "$0: can't create command pipe: $!";
  229.     nocloexec(\*COMMAND_READ);
  230.     COMMAND_WRITE->autoflush(1);
  231.  
  232.     pipe DEBCONF_COMMAND_READ, DEBCONF_COMMAND_WRITE
  233.         or die "$0: can't create debconf command pipe: $!";
  234.     nonblock(\*DEBCONF_COMMAND_READ);
  235.     checkdup2(fileno(DEBCONF_COMMAND_WRITE), 6);
  236.     open DEBCONF_COMMAND_WRITE, '>&=6'
  237.         or die "$0: can't reopen DEBCONF_COMMAND_WRITE as fd 6: $!";
  238.     nocloexec(\*DEBCONF_COMMAND_WRITE);
  239.  
  240.     pipe DEBCONF_REPLY_READ, DEBCONF_REPLY_WRITE
  241.         or die "$0: can't create debconf reply pipe: $!";
  242.     checkdup2(fileno(DEBCONF_REPLY_READ), 5);
  243.     open DEBCONF_REPLY_READ, '<&=5'
  244.         or die "$0: can't reopen DEBCONF_REPLY_READ as fd 5: $!";
  245.     nocloexec(\*DEBCONF_REPLY_READ);
  246.     DEBCONF_REPLY_WRITE->autoflush(1);
  247.  
  248.     if (defined $logfile) {
  249.         open APT_LOG, '>>', $logfile
  250.             or die "$0: can't open $logfile: $!";
  251.     } elsif ($logstderr) {
  252.         open APT_LOG, '>&STDERR'
  253.             or die "$0: can't duplicate stderr: $!";
  254.     } else {
  255.         open APT_LOG, '>', '/dev/null'
  256.             or die "$0: can't open /dev/null: $!";
  257.     }
  258.     nocloexec(\*APT_LOG);
  259.  
  260.     $pid = passthrough $command,
  261.         '-o', 'APT::Status-Fd=4',
  262.         '-o', 'APT::Keep-Fds::=5',
  263.         '-o', 'APT::Keep-Fds::=6',
  264.         @_;
  265.  
  266.     my $status_eof = 0;
  267.     my $debconf_command_eof = 0;
  268.     my $status_buf = '';
  269.     my $debconf_command_buf = '';
  270.  
  271.     while (not $status_eof) {
  272.         my $rin = '';
  273.         my $rout;
  274.         vec($rin, fileno(STATUS_READ), 1) = 1;
  275.         vec($rin, fileno(DEBCONF_COMMAND_READ), 1) = 1
  276.             unless $debconf_command_eof;
  277.         my $sel = select($rout = $rin, undef, undef, undef);
  278.         if ($sel < 0) {
  279.             next if $! == &POSIX::EINTR;
  280.             die "$0: select failed: $!";
  281.         }
  282.  
  283.         if (vec($rout, fileno(STATUS_READ), 1) == 1) {
  284.             while (1) {
  285.                 my $r = sysread(STATUS_READ, $status_buf, 4096,
  286.                         length $status_buf);
  287.                 if (not defined $r) {
  288.                     next if $! == &POSIX::EINTR;
  289.                     last if $! == &POSIX::EAGAIN or
  290.                         $! == &POSIX::EWOULDBLOCK;
  291.                     die "$0: read STATUS_READ failed: $!";
  292.                 }
  293.                 elsif ($r == 0) {
  294.                     if ($status_buf ne '' and
  295.                         $status_buf !~ /\n$/) {
  296.                         $status_buf .= "\n";
  297.                     }
  298.                     $status_eof = 1;
  299.                     last;
  300.                 }
  301.                 last if $status_buf =~ /\n/;
  302.             }
  303.  
  304.             while ($status_buf =~ /\n/) {
  305.                 my $status_line;
  306.                 ($status_line, $status_buf) =
  307.                     split /\n/, $status_buf, 2;
  308.                 handle_status $from, $to, $status_line;
  309.             }
  310.         }
  311.  
  312.         if (vec($rout, fileno(DEBCONF_COMMAND_READ), 1) == 1) {
  313.             while (1) {
  314.                 my $r = sysread(DEBCONF_COMMAND_READ,
  315.                         $debconf_command_buf, 4096,
  316.                         length $debconf_command_buf);
  317.                 if (not defined $r) {
  318.                     next if $! == &POSIX::EINTR;
  319.                     last if $! == &POSIX::EAGAIN or
  320.                         $! == &POSIX::EWOULDBLOCK;
  321.                     die "$0: read DEBCONF_COMMAND_READ " .
  322.                         "failed: $!";
  323.                 }
  324.                 elsif ($r == 0) {
  325.                     if ($debconf_command_buf ne '' and
  326.                         $debconf_command_buf !~ /\n$/) {
  327.                         $debconf_command_buf .= "\n";
  328.                     }
  329.                     $debconf_command_eof = 1;
  330.                     last;
  331.                 }
  332.                 last if $debconf_command_buf =~ /\n/;
  333.             }
  334.  
  335.             while ($debconf_command_buf =~ /\n/) {
  336.                 my $debconf_command_line;
  337.                 ($debconf_command_line, $debconf_command_buf) =
  338.                     split /\n/, $debconf_command_buf, 2;
  339.                 handle_debconf_command $debconf_command_line;
  340.             }
  341.         }
  342.     }
  343.  
  344.     waitpid $pid, 0;
  345.     undef $pid;
  346.     my $status = $?;
  347.  
  348.     if ($progress) {
  349.         my @ret=Debconf::Client::ConfModule::progress('SET', $to);
  350.         if ($ret[0] eq '30') {
  351.             cancel();
  352.         }
  353.     }
  354.  
  355.     if ($status & 127) {
  356.         return 127;
  357.     }
  358.  
  359.     return ($status >> 8);
  360. }
  361.  
  362. my $cancelled=0;
  363. my $cancel_sent_signal=0;
  364. sub cancel () {
  365.     $cancelled++;
  366.     if (defined $pid) {
  367.         $cancel_sent_signal++;
  368.         if ($cancel_sent_signal == 1) {
  369.             kill INT => $pid;
  370.         }
  371.         else {
  372.             kill KILL => $pid;
  373.         }
  374.     }
  375. }
  376.  
  377. sub start_bar ($$) {
  378.     my ($from, $to) = @_;
  379.     if ($progress) {
  380.         Debconf::Client::ConfModule::progress(
  381.             'START', $from, $to, 'debconf-apt-progress/title');
  382.         my @ret=Debconf::Client::ConfModule::progress(
  383.             'INFO', 'debconf-apt-progress/preparing');
  384.         if ($ret[0] eq '30') {
  385.             cancel();
  386.         }
  387.     }
  388. }
  389.  
  390. sub stop_bar () {
  391.     Debconf::Client::ConfModule::progress('STOP') if $progress;
  392.     Debconf::Client::ConfModule::stop() unless $had_frontend;
  393. }
  394.  
  395. if (envnonempty('DEBCONF_APT_PROGRESS_DB_REPLACE')) {
  396.     $ENV{DEBCONF_DB_REPLACE} = $ENV{DEBCONF_APT_PROGRESS_DB_REPLACE};
  397. } else {
  398.     delete $ENV{DEBCONF_DB_REPLACE};
  399. }
  400. if (envnonempty('DEBCONF_APT_PROGRESS_DB_OVERRIDE')) {
  401.     $ENV{DEBCONF_DB_OVERRIDE} = $ENV{DEBCONF_APT_PROGRESS_DB_OVERRIDE};
  402. } else {
  403.     delete $ENV{DEBCONF_DB_OVERRIDE};
  404. }
  405. $had_frontend = 1 unless $ENV{DEBCONF_APT_PROGRESS_NO_FRONTEND};
  406. delete $ENV{DEBCONF_APT_PROGRESS_NO_FRONTEND}; # avoid inheritance
  407.  
  408. my @saved_argv = @ARGV;
  409.  
  410. my $result = GetOptions('config'       => \$config,
  411.             'start'        => \$start,
  412.             'from=i'       => \$from,
  413.             'to=i'         => \$to,
  414.             'stop'         => \$stop,
  415.             'logfile=s'    => \$logfile,
  416.             'logstderr'    => \$logstderr,
  417.             'progress!'    => \$progress,
  418.             'dlwaypoint=i' => \$dlwaypoint,
  419. );
  420.  
  421. if (! $progress && ($start || $from || $to || $stop)) {
  422.     die "--no-progress cannot be used with --start, --from, --to, or --stop\n";
  423. }
  424.  
  425. unless ($start) {
  426.     if (defined $from and not defined $to) {
  427.         die "$0: --from requires --to\n";
  428.     } elsif (defined $to and not defined $from) {
  429.         die "$0: --to requires --from\n";
  430.     }
  431. }
  432.  
  433. my $mutex = 0;
  434. ++$mutex if $config;
  435. ++$mutex if $start;
  436. ++$mutex if $stop;
  437. if ($mutex > 1) {
  438.     die "$0: must use only one of --config, --start, or --stop\n";
  439. }
  440.  
  441. if (($config or $stop) and (defined $from or defined $to)) {
  442.     die "$0: cannot use --from or --to with --config or --stop\n";
  443. }
  444.  
  445. start_debconf(@saved_argv) unless $config;
  446.  
  447. my $status = 0;
  448.  
  449. if ($config) {
  450.     print <<'EOF';
  451. DEBCONF_APT_PROGRESS_DB_REPLACE="$DEBCONF_DB_REPLACE"
  452. DEBCONF_APT_PROGRESS_DB_OVERRIDE="$DEBCONF_DB_OVERRIDE"
  453. export DEBCONF_APT_PROGRESS_DB_REPLACE DEBCONF_APT_PROGRESS_DB_OVERRIDE
  454. DEBCONF_DB_REPLACE=configdb
  455. DEBCONF_DB_OVERRIDE='Pipe{infd:none outfd:none}'
  456. export DEBCONF_DB_REPLACE DEBCONF_DB_OVERRIDE
  457. EOF
  458. } elsif ($start) {
  459.     $from = 0 unless defined $from;
  460.     $to = 100 unless defined $to;
  461.     start_bar($from, $to);
  462. } elsif (defined $from) {
  463.     $status = run_progress($from, $to, @ARGV);
  464. } elsif ($stop) {
  465.     stop_bar();
  466. } else {
  467.     start_bar(0, 100);
  468.     if (! $cancelled) {
  469.         $status = run_progress(0, 100, @ARGV);
  470.         stop_bar();
  471.     }
  472. }
  473.  
  474. if ($cancelled) {
  475.     Debconf::Client::ConfModule::get("debconf/priority");
  476.  
  477.     exit 30;
  478. }
  479. elsif ($status == 30) {
  480.     exit 3;
  481. }
  482. else {
  483.     exit $status;
  484. }
  485.  
  486.